﻿namespace Grep.SharePoint.SmartDocuments
{
    using System;
    using Lib.Extensions;
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.WebControls;
    using Microsoft.SharePoint.WebPartPages;

    internal sealed class ListViewTemplateConnector
    {
        private readonly string _destinationFolderUrl;
        private readonly SPList _list;
        private readonly ListViewWebPart _listView;
        private TemplateLibraryConnectorSettings _settings;
        private int _uniqueCounter;

        public ListViewTemplateConnector(ListViewWebPart listView)
        {
            _listView = listView;
            _list = listView.GetList();
            _destinationFolderUrl = listView.GetRootFolder(false);
        }

        /// <summary>
        /// Recursive function to unfold a template document library into a menu hierarchy
        /// </summary>
        private void AddFolderContentsToMenu(SubMenuTemplate menu, SPFolder folder, string targetFolderUrl)
        {
            foreach (SPFolder subFolder in folder.SubFolders)
            {
                // Only parse real item folders
                if (subFolder.Item == null)
                {
                    continue;
                }

                // Add a sub menu level and recurse into that
                SubMenuTemplate subMenu = menu.AddSubMenu(GetMenuItemUniqueId(), subFolder.Item.Name,
                                                          "/_layouts/images/FLDRNEW.GIF", "");
                AddFolderContentsToMenu(subMenu, subFolder, targetFolderUrl);
            }

            // Add all files from the folder
            foreach (SPFile file in folder.Files)
            {
                SPListItem fileItem = file.Item;

                // Ignore non-items
                if (fileItem == null)
                {
                    continue;
                }

                // Add file menu item
                menu.AddMenuItem(GetMenuItemUniqueId(),
                                 fileItem.GetValueOrDefault("Title", fileItem.File.Name),
                                 fileItem.File.IconUrl.StartsWith("ic")
                                     ? "lg_" + fileItem.File.IconUrl
                                     : fileItem.File.IconUrl,
                                 fileItem.GetValueOrDefault(
                                     _settings.DescriptionFieldName, ""),
                                 "",
                                 @"javascript:createNewDocumentWithProgID('" +
                                 fileItem.ParentList.ParentWeb.Url + "/" +
                                 fileItem.File.Url +
                                 "', '" + targetFolderUrl +
                                 "', 'SharePoint.OpenDocuments', false)");
            }
        }

        /// <summary>
        /// Retrieve a unique identifier for use with menu items.
        /// </summary>
        private string GetMenuItemUniqueId()
        {
            return "GSDMid" + (++_uniqueCounter);
        }

        /// <summary>
        /// Attempt to open the template document library, based on the webpart's properties.
        /// </summary>
        private SPDocumentLibrary GetTemplateDocumentLibrary()
        {
            if (!string.IsNullOrEmpty(_settings.WebId) &&
                !string.IsNullOrEmpty(_settings.TemplateListId))
            {
                SPWeb web = null;
                try
                {
                    web = OpenContextSiteWebById(_settings.WebId);
                    if (web == null)
                    {
                        // Invalid web - return null
                        return null;
                    }
                    return web.Lists.GetList(new Guid(_settings.TemplateListId), false) as SPDocumentLibrary;
                }
                catch
                {
                    /* Error fetching list, or invalid list id: in either case return null */
                }
                finally
                {
                    if (web != null)
                    {
                        web.Dispose();
                    }
                }
            }
            return null;
        }

        /// <summary>
        /// Open the webpart's source web, based on the properties.
        /// 'Open' implies that ownership of the SPWeb object is passed on
        /// to the caller. Clearly put: If you get a SPWeb from this function,
        /// *you* should Dispose() it.
        /// </summary>
        /// <returns></returns>
        private static SPWeb OpenContextSiteWebById(string webId)
        {
            SPSite site = SPContext.Current.Site;
            SPWeb web = null;
            web = site.OpenWeb(new Guid(webId));
            return web;
        }

        public void SetupTemplateLibraryConnections()
        {
            if (_list == null)
            {
                // No list assigned. Probably indicates an inconsistency between the assigned
                // ListViewWebPart and the hosting SPWeb. Perhaps no hosting web?
                return;
            }

            TemplateLibraryConnectorSettings settings = TemplateLibraryConnectorSettings.LoadFromList(_list);
            if (settings == null ||
                settings.Enabled == false)
            {
                // This list isn't enabled for Template Connections
                return;
            }
            _settings = settings;

            NewMenu newMenu = _listView.GetNewMenu();
            if (newMenu == null)
            {
                // No NewMenu: nowhere to add our template entries
                return;
            }

            SPDocumentLibrary templateLibrary = GetTemplateDocumentLibrary();
            if (templateLibrary == null)
            {
                // No tepmlate library: nothing to add
                return;
            }

            UnfoldTemplateStructure(templateLibrary, newMenu, _destinationFolderUrl);
        }

        /// <summary>
        /// Initialize recursion through the template document library, and add it to a templates submeny of the
        /// passed NewMenu. This 'NewMenu' should correspond with the ListView's NewMenu.
        /// </summary>
        private void UnfoldTemplateStructure(SPDocumentLibrary templateLibrary, NewMenu newMenu, string targetFolderUrl)
        {
            SubMenuTemplate templateRootMenu = newMenu.AddSubMenu(GetMenuItemUniqueId(), "Templates",
                                                                  "/_layouts/images/FLDRNEW.GIF",
                                                                  "Create new document from a template");
            AddFolderContentsToMenu(templateRootMenu, templateLibrary.RootFolder, targetFolderUrl);
        }
    }
}